package com.ssau.expert.gui.user;

import com.ssau.expert.app.AppConfig;
import com.ssau.expert.app.AppContext;
import com.ssau.expert.app.ExpertAPI;
import com.ssau.expert.common.Answer;
import com.ssau.expert.common.Question;
import com.ssau.expert.common.QuestionRequestListener;
import com.ssau.expert.core.impl.ExpertSystem;
import com.ssau.expert.gui.app.Locator;
import com.ssau.expert.gui.common.Controller;
import com.ssau.expert.gui.common.MyControls;
import com.ssau.expert.util.Names;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.util.List;

/**
 * Author: 345
 * Date: 09.10.13 18:26
 */
public class UserFrame extends JFrame implements UserPresenter, QuestionRequestListener {

    private static final String NAME = "ЭС. Режим пользователя.";

    private static final Dimension SIZE = new Dimension(415, 670);
    private static final Dimension PANEL_SIZE = new Dimension(SIZE.width - 35, 120);
    private static final Dimension R_SIZE = new Dimension(SIZE.width - 35, 180);
    private static final Dimension B_SIZE = new Dimension(SIZE.width - 35, 50);
    private static final Dimension TF_SIZE = new Dimension(PANEL_SIZE.width - 10, 110);

    private ExpertAPI expertAPI;

    private UserFrame() {
    }

    @Override
    public void init() {

        initDisposition();
        initComponents();
    }

    @Override
    public Answer onQuestionRequest(final Question question, boolean askFirstTime) {
        if (!askFirstTime) {
            showMessageDialog("Внимание", "Некорректный тип введенных данных");
        }

        Answer answer;
        TextField t1 = new TextField();
        TextField t2 = new TextField();
        TextField t3 = new TextField();
        TextField t4 = new TextField();

        if (!Names.isFuzzy(question.getVariableName())) {
            Component[] inputs = new Component[]{new Label("Значение"), t1};
            JOptionPane.showMessageDialog(null, inputs, question.getQuestionString(), JOptionPane.PLAIN_MESSAGE);
            answer = new Answer(t1.getText(), 100);
            return answer;
        } else {
            Component[] inputs = new Component[]{
                    new Label("Значение1"),
                    t1,
                    new Label("CF1"),
                    t2};//, new Label("Значение2"), t3, new Label("CF2"), t4}

            boolean firstStep = false;
            int[] finalValues = new int[4];
            String varVal = "";
            String cfVal = "";

            while (!firstStep) {
                JOptionPane.showMessageDialog(null, inputs, question.getQuestionString(), JOptionPane.PLAIN_MESSAGE);

                varVal = t1.getText();
                cfVal = t2.getText();

                try {
                    int varInt = Integer.valueOf(varVal);
                    int cfInt = Integer.valueOf(cfVal);

                    if (cfInt < 0 || cfInt > 100) {
                        throw new Exception("Fuck oop");
                    }

                    finalValues[0] = varInt;
                    finalValues[1] = cfInt;

                    firstStep = true;
                } catch (Exception ex) {
                    showMessageDialog("Внимание", "Некорректные данные");
                }
            }

            if (finalValues[1] == 100) {
                answer = new Answer(varVal, 100);
                return answer;
            } else {
                Component[] inputs2 = new Component[]{
                        new Label("Значение2"),
                        t3,
                        new Label("CF2"),
                        t4};

                boolean secondStep = false;

                while (!secondStep) {
                    JOptionPane.showMessageDialog(null, inputs2, question.getQuestionString(), JOptionPane.PLAIN_MESSAGE);

                    varVal = t3.getText();
                    cfVal = t4.getText();

                    try {
                        int varInt = Integer.valueOf(varVal);
                        int cfInt = Integer.valueOf(cfVal);

                        if (cfInt < 0 || cfInt > 100) {
                            throw new Exception("Fuck oop");
                        }

                        finalValues[2] = varInt;
                        finalValues[3] = cfInt;

                        if (cfInt + finalValues[1] > 100) {
                            showMessageDialog("Внимание", "Сумма коэффициентов уверенности больше 100");
                        } else {
                            secondStep = true;
                        }
                    } catch (Exception ex) {
                        showMessageDialog("Внимание", "Некорректные данные");
                    }
                }

                answer = new Answer(String.valueOf(finalValues[0]), finalValues[1], String.valueOf(finalValues[2]), finalValues[3]);
                return answer;
            }
        }
    }

    private void initComponents() {
        expertAPI = AppContext.get().getBean(ExpertSystem.class);

        JPanel mainPanel = MyControls.createPanel(5, 5, SIZE.width - 25, PANEL_SIZE.height * 3 + B_SIZE.height + R_SIZE.height + 30, "");
        mainPanel.setLayout(null);
        add(mainPanel);

        JPanel profilePanel = MyControls.createPanel(5, 5, PANEL_SIZE.width, PANEL_SIZE.height, "");
        profilePanel.setLayout(null);
        profileJTextField = new JTextArea();
        profileJTextField.setText("Профиль");
        profileJTextField.setLocation(5, 5);
        profileJTextField.setSize(TF_SIZE);
        profileJTextField.setFocusable(false);
        profilePanel.add(profileJTextField);
        mainPanel.add(profilePanel);

        JPanel distancePanel = MyControls.createPanel(5, PANEL_SIZE.height + 10, PANEL_SIZE.width, PANEL_SIZE.height, "");
        distancePanel.setLayout(null);
        distanceJTextField = new JTextArea();
        distanceJTextField.setText("Автономность");
        distanceJTextField.setSize(TF_SIZE);
        distanceJTextField.setLocation(5, 5);
        distanceJTextField.setFocusable(false);
        distancePanel.add(distanceJTextField);
        mainPanel.add(distancePanel);

        JPanel staffPanel = MyControls.createPanel(5, 2 * PANEL_SIZE.height + 15, PANEL_SIZE.width, PANEL_SIZE.height, "");
        staffPanel.setLayout(null);
        staffJTextField = new JTextArea();
        staffJTextField.setText("Персонал");
        staffJTextField.setSize(TF_SIZE);
        staffJTextField.setLocation(5, 5);
        staffJTextField.setFocusable(false);
        staffPanel.add(staffJTextField);
        mainPanel.add(staffPanel);

        JPanel resultPanel = MyControls.createPanel(5, 3 * PANEL_SIZE.height + 20, PANEL_SIZE.width, R_SIZE.height, "");
        resultPanel.setLayout(null);
        resultTextArea = new JTextArea();
        resultTextArea.setText("Результат");
        resultTextArea.setLocation(5, 5);
        resultTextArea.setSize(new Dimension(R_SIZE.width - 10, R_SIZE.height - 10));
        resultTextArea.setFocusable(false);
        resultPanel.add(resultTextArea);
        mainPanel.add(resultPanel);

        JPanel buttonsPanel = MyControls.createPanel(5, 3 * PANEL_SIZE.height + R_SIZE.height + 25, PANEL_SIZE.width,
                B_SIZE.height, "");
        buttonsPanel.setLayout(null);
        mainPanel.add(buttonsPanel);

        startConsultationJButton = new JButton("Консультация");
        startConsultationJButton.setLocation(0, 0);
        startConsultationJButton.setSize(MyControls.BUTTON_SIZE);
        buttonsPanel.add(startConsultationJButton);
        startConsultationJButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                displayUserInput(null, null, null);
                resultTextArea.setText("");
                expertAPI.setAlgebra(r1.isSelected() ? "AM" : "BP");
                startConsultation();
            }
        });

        logButton = new JButton("Объяснение решения");
        buttonsPanel.add(logButton);
        logButton.setLocation(0, 25);
        logButton.setSize(MyControls.BUTTON_SIZE);
        logButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                displayLog();
            }
        });

        helpButton = new JButton("Справка");
        buttonsPanel.add(helpButton);
        helpButton.setSize(MyControls.BUTTON_SIZE);
        helpButton.setLocation(MyControls.BUTTON_SIZE.width, 25);
        helpButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                displayHelp();
            }
        });

        ButtonGroup buttonGroup = new ButtonGroup();
        r1 = new JRadioButton("AM", true);
        r1.setSize(new Dimension(95, 25));
        r1.setLocation(MyControls.BUTTON_SIZE.width, 0);

        r2 = new JRadioButton("BP", false);
        r2.setSize(new Dimension(95, 25));
        r2.setLocation(MyControls.BUTTON_SIZE.width + 95, 0);
        buttonGroup.add(r1);
        buttonGroup.add(r2);
        buttonsPanel.add(r1);
        buttonsPanel.add(r2);
    }

    protected JRadioButton r2;
    protected JRadioButton r1;

    @Override
    public void setEnableRadio(boolean enable) {
        r1.setEnabled(enable);
        r2.setEnabled(enable);
    }

    private void displayHelp() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("help.txt"));
        } catch (FileNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Файл справки не неайден");
        }
        try {
            StringBuilder sb = new StringBuilder();
            String line = br != null ? br.readLine() : "";

            while (line != null) {
                sb.append(line);
                sb.append('\n');
                line = br != null ? br.readLine() : "";
            }
            String everything = sb.toString();
            JOptionPane.showMessageDialog(this, everything, "Справка", JOptionPane.INFORMATION_MESSAGE);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
            }
        }
    }

    private void initDisposition() {
        setSize(SIZE);
        setTitle(NAME);
        setLayout(null);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                Controller.get().showLoginFrame();
            }
        });
    }

    @Override
    public void showFrame() {
        setName(NAME);
        setTitle(NAME);
        setVisible(true);
    }

    @Override
    public void showMessageDialog(String title, String message) {
        JOptionPane.showMessageDialog(this, message, title, JOptionPane.INFORMATION_MESSAGE);
    }

    @Override
    public void showMessageDialog(String message) {
        JOptionPane.showMessageDialog(this, message);
    }

    @Override
    public void addElementToResultList(String element) {
        resultTextArea.setText(resultTextArea.getText() + "\n" + element);
    }

    @Override
    public void displayUserInput(Answer shipProfileAnswer, Answer staffAnswer, Answer distanceAnswer) {
        addText(profileJTextField, shipProfileAnswer, true);
        addText(distanceJTextField, distanceAnswer, false);
        addText(staffJTextField, staffAnswer, false);
    }

    protected void addText(JTextArea tf, Answer answer, boolean shipProfile) {
        String txt = tf.getText();
        if (shipProfile) {
            txt += answer != null ? "\n" + answer.getValue1() : "";
        } else {
            txt += answer != null ? "\n" + answer.format() : "";
        }
        tf.setText(txt);
    }

    @Override
    public void clearResultListModel() {
        profileJTextField.setText("Профиль");
        distanceJTextField.setText("Автономность");
        staffJTextField.setText("Персонал");
        resultTextArea.setText("Результат");
    }

    @Override
    public String showInputDialog(String questionString) {
        return JOptionPane.showInputDialog(this, questionString);
    }

    @Override
    public String showInputDialog(String title, String questionString) {
        return JOptionPane.showInputDialog(this, questionString, title, JOptionPane.INFORMATION_MESSAGE);
    }

    @Override
    public void displayLog() {
        List<String> log = Locator.getExpert().getLog();

        try {
            File f = new File(AppConfig.getLogFilePath());
            FileUtils.writeLines(f, log);
            List<String> logList = Locator.getExpert().getLog();
            String allLog = "";
            for (String str : logList) {
                allLog += "\n" + str;
            }
            //JOptionPane.showMessageDialog(this, allLog);
        } catch (IOException ex) {
            System.out.println("Catched IO ex while saving log.");
            System.out.println(ex.getMessage());
        }

        showMessageDialog(String.format("Лог работы системы сохранен в файл '%s'", AppConfig.getLogFilePath()));
    }

    private void startConsultation() {
        Controller.get().startConsultation();
    }

    private JButton startConsultationJButton;
    private JButton logButton;

    private JPanel userEntredPanel;
    private JTextArea profileJTextField;
    private JTextArea distanceJTextField;
    private JTextArea staffJTextField;
    private JTextArea toProveJTextArea;
    private DefaultListModel<String> resultListModel;
    private JList<String> resList;
    private JTextArea resultTextArea;
    private JButton helpButton;

    private static UserFrame instance;

    public static UserFrame get() {
        if (instance == null) {
            instance = new UserFrame();
        }
        return instance;
    }
}
